#include <SceneNode.h>
#include <Scene2D.h>
#include <D3D9Renderer.h>

void SceneNode2DProperties::Transform(Mat4x4 *toWorld, Mat4x4 *fromWorld) const
{
	if (toWorld)
		*toWorld = m_toWorld;

	if(fromWorld)
		*fromWorld = m_fromWorld;
}

SceneNode2D::~SceneNode2D()
{
	m_children.clear();
}

HRESULT SceneNode2D::VRestore(Scene2D *pScene)
{
	auto i = m_children.begin();
	auto end = m_children.end();
	while (i != end)
	{
		(*i)->VRestore(pScene);
		i++;
	}
	return S_OK;
}

void SceneNode2D::VSetTransform()
{
	D3DXMatrixTransformation2D(&m_props.m_toWorld, NULL, 0, &m_scale, &(m_props.m_size/2), m_props.m_orientation, &m_props.m_position);
	m_props.m_fromWorld = m_props.m_toWorld.Inverse();
}

HRESULT SceneNode2D::VPreRender(Scene2D *pScene) 
{
	VSetTransform();
	pScene->PushAndSetMatrix(m_props.m_toWorld);
	return S_OK;
}

HRESULT SceneNode2D::VPostRender(Scene2D *pScene) 
{
	pScene->PopMatrix();
	return S_OK;
}

bool SceneNode2D::VIsVisible(Scene2D *pScene)
{
	//TODO
	return true;
}

void SceneNode2D::VUpdate(Scene2D* pScene, double deltaSecs)
{
	auto i = m_children.begin();
	auto end = m_children.end();

	while (i != end)
	{
		(*i)->VUpdate(pScene, deltaSecs);
		i++;
	}
}

HRESULT SceneNode2D::VRender(Scene2D *pScene)
{
	return S_OK;
}

HRESULT SceneNode2D::VRenderChildren(Scene2D *pScene)
{
	// Iterate through the children....
	auto i = m_children.begin();
	auto end = m_children.end();

	while (i != end)
	{
		if ((*i)->VPreRender(pScene)==S_OK)
		{
			// You could short-circuit rendering
			// if an object returns E_FAIL from
			// VPreRender()

			// Don't render this node if you can't see it
			if ((*i)->VIsVisible(pScene))
			{
				HR((*i)->VRender(pScene));	
			}

			HR((*i)->VRenderChildren(pScene));
		}
		HR((*i)->VPostRender(pScene));
		i++;
	}

	return S_OK;
}

bool SceneNode2D::VAddChild(std::shared_ptr<ISceneNode2D> kid)
{
	m_children.push_back(kid);
	return true;
}

bool SceneNode2D::VRemoveChild(ActorId id)
{
	for(auto i=m_children.begin(); i!=m_children.end(); ++i)
	{
		const SceneNode2DProperties* pProps = (*i)->VGet();
		if(pProps->ActorId() != 0 && id== pProps->ActorId())
		{
			i = m_children.erase(i);	//this can be expensive for vectors
			return true;
		}
	}
	return false;
}

HRESULT SceneNode2D::VPick(Scene2D *pScene, const Vec2& Position) 
{
	for(auto i=m_children.begin(); i!=m_children.end(); ++i)
	{
		HRESULT hr = (*i)->VPick(pScene, Position);

		if (hr==E_FAIL)
			return E_FAIL;
	}

	return S_OK;
}

